/*-------------------------------------------------------------------------
 *
 * readfuncs.c
 *	  Postgres树节点的读取函数。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/nodes/readfuncs.c
 *
 * NOTES
 *	  路径节点没有任何读取函数支持，因为我们从未有机会读取它们。（曾经有代码声称可以读取它们，但它也已损坏且未使用。）我们也从不读取执行器状态树。
 *
 *	  解析位置字段由outfuncs.c输出，但仅用于调试。读取位置字段时，我们通常会丢弃存储的值并将位置字段设置为-1（即"未知"）。这是因为来自存储规则的节点不应被认为在当前查询文本中具有已知位置。
 *	  然而，如果restore_location_fields为真，我们将从字符串中恢复位置字段。这目前仅供WRITE_READ_PARSE_PLAN_TREES测试代码使用，后者不希望在节点内容上造成任何变化。
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <math.h>

#include "miscadmin.h"
#include "nodes/extensible.h"
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h"
#include "nodes/readfuncs.h"



/*
 * 宏用于简化读取不同类型字段的操作。尽可能使用这些宏，以减少发生低级错误的机会。注意，这些宏硬性规定了 Read 例程中局部变量的命名约定。
 */

/* 声明适当局部变量的宏 */

/* 有些仅需要 local_node */
#define READ_LOCALS_NO_FIELDS(nodeTypeName) \
	nodeTypeName *fc_local_node = makeNode(nodeTypeName)

/* 有些仅需要 pg_strtok 支持字段 */
#define READ_TEMP_LOCALS()	\
	const char *fc_token;		\
	int			fc_length

/* ... 但大多数需要两者 */
#define READ_LOCALS(nodeTypeName)			\
	READ_LOCALS_NO_FIELDS(nodeTypeName);	\
	READ_TEMP_LOCALS()

/* 读取一个整数字段（任何写成“:fldname %d”的内容） */
#define READ_INT_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = atoi(fc_token)

/* 读取一个无符号整数字段（任何写成“:fldname %u”的内容） */
#define READ_UINT_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = atoui(fc_token)

/* 读取一个无符号整数字段（任何使用 UINT64_FORMAT 写的内容） */
#define READ_UINT64_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = strtou64(fc_token, NULL, 10)

/* 读取一个长整数字段（任何写成“:fldname %ld”的内容） */
#define READ_LONG_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = atol(fc_token)

/* 读取一个 OID 字段（不要硬编码假设 OID 与 uint 相同） */
#define READ_OID_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = atooid(fc_token)

/* 读取一个字符字段（即一个 ASCII 字符） */
#define READ_CHAR_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	/* 避免为一个字符调用 debackslash() 的开销 */ \
	fc_local_node->fldname = (fc_length == 0) ? '\0' : (fc_token[0] == '\\' ? fc_token[1] : fc_token[0])

/* 读取一个以整数代码写的枚举类型字段 */
#define READ_ENUM_FIELD(fldname, enumtype) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = (enumtype) atoi(fc_token)

/* 读取一个浮点字段 */
#define READ_FLOAT_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = atof(fc_token)

/* 读取一个布尔字段 */
#define READ_BOOL_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = strtobool(fc_token)

/* 读取一个字符字符串字段 */
#define READ_STRING_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = nullable_string(fc_token, fc_length)

/* 读取一个解析位置字段（并可能丢弃该值） */
#ifdef WRITE_READ_PARSE_PLAN_TREES
#define READ_LOCATION_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	fc_local_node->fldname = restore_location_fields ? atoi(fc_token) : -1
#else
#define READ_LOCATION_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_token = pg_strtok(&fc_length);		/* 获取字段值 */ \
	(void) fc_token;				/* 以防在其他地方未使用 */ \
	fc_local_node->fldname = -1	/* 将字段设置为“未知” */
#endif

/* 读取一个节点字段 */
#define READ_NODE_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	(void) fc_token;				/* 以防在其他地方未使用 */ \
	fc_local_node->fldname = nodeRead(NULL, 0)

/* 读取一个位图集字段 */
#define READ_BITMAPSET_FIELD(fldname) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	(void) fc_token;				/* 以防在其他地方未使用 */ \
	fc_local_node->fldname = fc__readBitmapset()

/* 读取一个属性编号数组 */
#define READ_ATTRNUMBER_ARRAY(fldname, len) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_local_node->fldname = readAttrNumberCols(len)

/* 读取一个 OID 数组 */
#define READ_OID_ARRAY(fldname, len) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_local_node->fldname = readOidCols(len)

/* 读取一个整数数组 */
#define READ_INT_ARRAY(fldname, len) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_local_node->fldname = readIntCols(len)

/* 读取一个布尔数组 */
#define READ_BOOL_ARRAY(fldname, len) \
	fc_token = pg_strtok(&fc_length);		/* 跳过 :fldname */ \
	fc_local_node->fldname = readBoolCols(len)

/* 例程退出 */
#define READ_DONE() \
	return fc_local_node


/*
 * 注意：使用 atoi() 读取以 %d 写的值，或在 outfuncs.c 中使用 atoui() 来读取
 * 以 %u 写的值。一个例外是 OID 值，
 * 使用 atooid()。 （截至 7.1，outfuncs.c 以 %u 写 OID，
 * 但这在未来可能会改变。）
 */
#define atoui(x)  ((unsigned int) strtoul((x), NULL, 10))

#define strtobool(x)  ((*(x) == 't') ? true : false)

#define nullable_string(token,length)  \
	((length) == 0 ? NULL : debackslash(token, length))


/*
 * _readBitmapset
 */
static Bitmapset * fc__readBitmapset(void)
{
	Bitmapset  *fc_result = NULL;

	READ_TEMP_LOCALS();

	fc_token = pg_strtok(&fc_length);
	if (fc_token == NULL)
		elog(ERROR, "incomplete Bitmapset structure");
	if (fc_length != 1 || fc_token[0] != '(')
		elog(ERROR, "unrecognized token: \"%.*s\"", fc_length, fc_token);

	fc_token = pg_strtok(&fc_length);
	if (fc_token == NULL)
		elog(ERROR, "incomplete Bitmapset structure");
	if (fc_length != 1 || fc_token[0] != 'b')
		elog(ERROR, "unrecognized token: \"%.*s\"", fc_length, fc_token);

	for (;;)
	{
		int			fc_val;
		char	   *fc_endptr;

		fc_token = pg_strtok(&fc_length);
		if (fc_token == NULL)
			elog(ERROR, "unterminated Bitmapset structure");
		if (fc_length == 1 && fc_token[0] == ')')
			break;
		fc_val = (int) strtol(fc_token, &fc_endptr, 10);
		if (fc_endptr != fc_token + fc_length)
			elog(ERROR, "unrecognized integer: \"%.*s\"", fc_length, fc_token);
		fc_result = bms_add_member(fc_result, fc_val);
	}

	return fc_result;
}

/*
 * 供定义可扩展节点的扩展使用
 */
Bitmapset * readBitmapset(void)
{
	return fc__readBitmapset();
}

/*
 * _readQuery
 */
static Query * fc__readQuery(void)
{
	READ_LOCALS(Query);

	READ_ENUM_FIELD(commandType, CmdType);
	READ_ENUM_FIELD(querySource, QuerySource);
	fc_local_node->queryId = UINT64CONST(0);	/* 不保存在输出格式中 */
	READ_BOOL_FIELD(canSetTag);
	READ_NODE_FIELD(utilityStmt);
	READ_INT_FIELD(resultRelation);
	READ_BOOL_FIELD(hasAggs);
	READ_BOOL_FIELD(hasWindowFuncs);
	READ_BOOL_FIELD(hasTargetSRFs);
	READ_BOOL_FIELD(hasSubLinks);
	READ_BOOL_FIELD(hasDistinctOn);
	READ_BOOL_FIELD(hasRecursive);
	READ_BOOL_FIELD(hasModifyingCTE);
	READ_BOOL_FIELD(hasForUpdate);
	READ_BOOL_FIELD(hasRowSecurity);
	READ_BOOL_FIELD(isReturn);
	READ_NODE_FIELD(cteList);
	READ_NODE_FIELD(rtable);
	READ_NODE_FIELD(jointree);
	READ_NODE_FIELD(targetList);
	READ_ENUM_FIELD(override, OverridingKind);
	READ_NODE_FIELD(onConflict);
	READ_NODE_FIELD(returningList);
	READ_NODE_FIELD(groupClause);
	READ_BOOL_FIELD(groupDistinct);
	READ_NODE_FIELD(groupingSets);
	READ_NODE_FIELD(havingQual);
	READ_NODE_FIELD(windowClause);
	READ_NODE_FIELD(distinctClause);
	READ_NODE_FIELD(sortClause);
	READ_NODE_FIELD(limitOffset);
	READ_NODE_FIELD(limitCount);
	READ_ENUM_FIELD(limitOption, LimitOption);
	READ_NODE_FIELD(rowMarks);
	READ_NODE_FIELD(setOperations);
	READ_NODE_FIELD(constraintDeps);
	READ_NODE_FIELD(withCheckOptions);
	READ_NODE_FIELD(mergeActionList);
	READ_BOOL_FIELD(mergeUseOuterJoin);
	READ_LOCATION_FIELD(stmt_location);
	READ_INT_FIELD(stmt_len);

	READ_DONE();
}

/*
 * _readNotifyStmt
 */
static NotifyStmt *
fc__readNotifyStmt(void)
{
	READ_LOCALS(NotifyStmt);

	READ_STRING_FIELD(conditionname);
	READ_STRING_FIELD(payload);

	READ_DONE();
}

/*
 * _readDeclareCursorStmt
 */
static DeclareCursorStmt *
fc__readDeclareCursorStmt(void)
{
	READ_LOCALS(DeclareCursorStmt);

	READ_STRING_FIELD(portalname);
	READ_INT_FIELD(options);
	READ_NODE_FIELD(query);

	READ_DONE();
}

/*
 * _readWithCheckOption
 */
static WithCheckOption *
fc__readWithCheckOption(void)
{
	READ_LOCALS(WithCheckOption);

	READ_ENUM_FIELD(kind, WCOKind);
	READ_STRING_FIELD(relname);
	READ_STRING_FIELD(polname);
	READ_NODE_FIELD(qual);
	READ_BOOL_FIELD(cascaded);

	READ_DONE();
}

/*
 * _readSortGroupClause
 */
static SortGroupClause *
fc__readSortGroupClause(void)
{
	READ_LOCALS(SortGroupClause);

	READ_UINT_FIELD(tleSortGroupRef);
	READ_OID_FIELD(eqop);
	READ_OID_FIELD(sortop);
	READ_BOOL_FIELD(nulls_first);
	READ_BOOL_FIELD(hashable);

	READ_DONE();
}

/*
 * _readGroupingSet
 */
static GroupingSet *
fc__readGroupingSet(void)
{
	READ_LOCALS(GroupingSet);

	READ_ENUM_FIELD(kind, GroupingSetKind);
	READ_NODE_FIELD(content);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readWindowClause
 */
static WindowClause * fc__readWindowClause(void)
{
	READ_LOCALS(WindowClause);

	READ_STRING_FIELD(name);
	READ_STRING_FIELD(refname);
	READ_NODE_FIELD(partitionClause);
	READ_NODE_FIELD(orderClause);
	READ_INT_FIELD(frameOptions);
	READ_NODE_FIELD(startOffset);
	READ_NODE_FIELD(endOffset);
	READ_NODE_FIELD(runCondition);
	READ_OID_FIELD(startInRangeFunc);
	READ_OID_FIELD(endInRangeFunc);
	READ_OID_FIELD(inRangeColl);
	READ_BOOL_FIELD(inRangeAsc);
	READ_BOOL_FIELD(inRangeNullsFirst);
	READ_UINT_FIELD(winref);
	READ_BOOL_FIELD(copiedOrder);

	READ_DONE();
}

/*
 * _readRowMarkClause
 */
static RowMarkClause *
fc__readRowMarkClause(void)
{
	READ_LOCALS(RowMarkClause);

	READ_UINT_FIELD(rti);
	READ_ENUM_FIELD(strength, LockClauseStrength);
	READ_ENUM_FIELD(waitPolicy, LockWaitPolicy);
	READ_BOOL_FIELD(pushedDown);

	READ_DONE();
}

/*
 * _readCTESearchClause
 */
static CTESearchClause *
fc__readCTESearchClause(void)
{
	READ_LOCALS(CTESearchClause);

	READ_NODE_FIELD(search_col_list);
	READ_BOOL_FIELD(search_breadth_first);
	READ_STRING_FIELD(search_seq_column);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCTECycleClause
 */
static CTECycleClause *
fc__readCTECycleClause(void)
{
	READ_LOCALS(CTECycleClause);

	READ_NODE_FIELD(cycle_col_list);
	READ_STRING_FIELD(cycle_mark_column);
	READ_NODE_FIELD(cycle_mark_value);
	READ_NODE_FIELD(cycle_mark_default);
	READ_STRING_FIELD(cycle_path_column);
	READ_LOCATION_FIELD(location);
	READ_OID_FIELD(cycle_mark_type);
	READ_INT_FIELD(cycle_mark_typmod);
	READ_OID_FIELD(cycle_mark_collation);
	READ_OID_FIELD(cycle_mark_neop);

	READ_DONE();
}

/*
 * _readCommonTableExpr
 */
static CommonTableExpr *
fc__readCommonTableExpr(void)
{
	READ_LOCALS(CommonTableExpr);

	READ_STRING_FIELD(ctename);
	READ_NODE_FIELD(aliascolnames);
	READ_ENUM_FIELD(ctematerialized, CTEMaterialize);
	READ_NODE_FIELD(ctequery);
	READ_NODE_FIELD(search_clause);
	READ_NODE_FIELD(cycle_clause);
	READ_LOCATION_FIELD(location);
	READ_BOOL_FIELD(cterecursive);
	READ_INT_FIELD(cterefcount);
	READ_NODE_FIELD(ctecolnames);
	READ_NODE_FIELD(ctecoltypes);
	READ_NODE_FIELD(ctecoltypmods);
	READ_NODE_FIELD(ctecolcollations);

	READ_DONE();
}

/*
 * _readMergeWhenClause
 */
static MergeWhenClause *
fc__readMergeWhenClause(void)
{
	READ_LOCALS(MergeWhenClause);

	READ_BOOL_FIELD(matched);
	READ_ENUM_FIELD(commandType, CmdType);
	READ_ENUM_FIELD(override, OverridingKind);
	READ_NODE_FIELD(condition);
	READ_NODE_FIELD(targetList);
	READ_NODE_FIELD(values);

	READ_DONE();
}

/*
 * _readMergeAction
 */
static MergeAction *
fc__readMergeAction(void)
{
	READ_LOCALS(MergeAction);

	READ_BOOL_FIELD(matched);
	READ_ENUM_FIELD(commandType, CmdType);
	READ_ENUM_FIELD(override, OverridingKind);
	READ_NODE_FIELD(qual);
	READ_NODE_FIELD(targetList);
	READ_NODE_FIELD(updateColnos);

	READ_DONE();
}

/*
 * _readSetOperationStmt
 */
static SetOperationStmt *
fc__readSetOperationStmt(void)
{
	READ_LOCALS(SetOperationStmt);

	READ_ENUM_FIELD(op, SetOperation);
	READ_BOOL_FIELD(all);
	READ_NODE_FIELD(larg);
	READ_NODE_FIELD(rarg);
	READ_NODE_FIELD(colTypes);
	READ_NODE_FIELD(colTypmods);
	READ_NODE_FIELD(colCollations);
	READ_NODE_FIELD(groupClauses);

	READ_DONE();
}


/*
 *	来自primnodes.h的内容。
 */

static Alias *
fc__readAlias(void)
{
	READ_LOCALS(Alias);

	READ_STRING_FIELD(aliasname);
	READ_NODE_FIELD(colnames);

	READ_DONE();
}

static RangeVar *
fc__readRangeVar(void)
{
	READ_LOCALS(RangeVar);

	fc_local_node->catalogname = NULL; /* 当前不保存于输出格式中 */

	READ_STRING_FIELD(schemaname);
	READ_STRING_FIELD(relname);
	READ_BOOL_FIELD(inh);
	READ_CHAR_FIELD(relpersistence);
	READ_NODE_FIELD(alias);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readTableFunc
 */
static TableFunc *
fc__readTableFunc(void)
{
	READ_LOCALS(TableFunc);

	READ_NODE_FIELD(ns_uris);
	READ_NODE_FIELD(ns_names);
	READ_NODE_FIELD(docexpr);
	READ_NODE_FIELD(rowexpr);
	READ_NODE_FIELD(colnames);
	READ_NODE_FIELD(coltypes);
	READ_NODE_FIELD(coltypmods);
	READ_NODE_FIELD(colcollations);
	READ_NODE_FIELD(colexprs);
	READ_NODE_FIELD(coldefexprs);
	READ_BITMAPSET_FIELD(notnulls);
	READ_INT_FIELD(ordinalitycol);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

static IntoClause *
fc__readIntoClause(void)
{
	READ_LOCALS(IntoClause);

	READ_NODE_FIELD(rel);
	READ_NODE_FIELD(colNames);
	READ_STRING_FIELD(accessMethod);
	READ_NODE_FIELD(options);
	READ_ENUM_FIELD(onCommit, OnCommitAction);
	READ_STRING_FIELD(tableSpaceName);
	READ_NODE_FIELD(viewQuery);
	READ_BOOL_FIELD(skipData);

	READ_DONE();
}

/*
 * _readVar
 */
static Var * fc__readVar(void)
{
	READ_LOCALS(Var);

	READ_INT_FIELD(varno);
	READ_INT_FIELD(varattno);
	READ_OID_FIELD(vartype);
	READ_INT_FIELD(vartypmod);
	READ_OID_FIELD(varcollid);
	READ_UINT_FIELD(varlevelsup);
	READ_UINT_FIELD(varnosyn);
	READ_INT_FIELD(varattnosyn);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readConst
 */
static Const * fc__readConst(void)
{
	READ_LOCALS(Const);

	READ_OID_FIELD(consttype);
	READ_INT_FIELD(consttypmod);
	READ_OID_FIELD(constcollid);
	READ_INT_FIELD(constlen);
	READ_BOOL_FIELD(constbyval);
	READ_BOOL_FIELD(constisnull);
	READ_LOCATION_FIELD(location);

	fc_token = pg_strtok(&fc_length); /* 跳过 :constvalue */
	if (fc_local_node->constisnull)
		fc_token = pg_strtok(&fc_length); /* 跳过 "<>" */
	else
		fc_local_node->constvalue = readDatum(fc_local_node->constbyval);

	READ_DONE();
}

/*
 * _readParam
 */
static Param *
fc__readParam(void)
{
	READ_LOCALS(Param);

	READ_ENUM_FIELD(paramkind, ParamKind);
	READ_INT_FIELD(paramid);
	READ_OID_FIELD(paramtype);
	READ_INT_FIELD(paramtypmod);
	READ_OID_FIELD(paramcollid);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readAggref
 */
static Aggref *
fc__readAggref(void)
{
	READ_LOCALS(Aggref);

	READ_OID_FIELD(aggfnoid);
	READ_OID_FIELD(aggtype);
	READ_OID_FIELD(aggcollid);
	READ_OID_FIELD(inputcollid);
	READ_OID_FIELD(aggtranstype);
	READ_NODE_FIELD(aggargtypes);
	READ_NODE_FIELD(aggdirectargs);
	READ_NODE_FIELD(args);
	READ_NODE_FIELD(aggorder);
	READ_NODE_FIELD(aggdistinct);
	READ_NODE_FIELD(aggfilter);
	READ_BOOL_FIELD(aggstar);
	READ_BOOL_FIELD(aggvariadic);
	READ_CHAR_FIELD(aggkind);
	READ_UINT_FIELD(agglevelsup);
	READ_ENUM_FIELD(aggsplit, AggSplit);
	READ_INT_FIELD(aggno);
	READ_INT_FIELD(aggtransno);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readGroupingFunc
 */
static GroupingFunc *
fc__readGroupingFunc(void)
{
	READ_LOCALS(GroupingFunc);

	READ_NODE_FIELD(args);
	READ_NODE_FIELD(refs);
	READ_NODE_FIELD(cols);
	READ_UINT_FIELD(agglevelsup);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readWindowFunc
 */
static WindowFunc *
fc__readWindowFunc(void)
{
	READ_LOCALS(WindowFunc);

	READ_OID_FIELD(winfnoid);
	READ_OID_FIELD(wintype);
	READ_OID_FIELD(wincollid);
	READ_OID_FIELD(inputcollid);
	READ_NODE_FIELD(args);
	READ_NODE_FIELD(aggfilter);
	READ_UINT_FIELD(winref);
	READ_BOOL_FIELD(winstar);
	READ_BOOL_FIELD(winagg);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readSubscriptingRef
 */
static SubscriptingRef *
fc__readSubscriptingRef(void)
{
	READ_LOCALS(SubscriptingRef);

	READ_OID_FIELD(refcontainertype);
	READ_OID_FIELD(refelemtype);
	READ_OID_FIELD(refrestype);
	READ_INT_FIELD(reftypmod);
	READ_OID_FIELD(refcollid);
	READ_NODE_FIELD(refupperindexpr);
	READ_NODE_FIELD(reflowerindexpr);
	READ_NODE_FIELD(refexpr);
	READ_NODE_FIELD(refassgnexpr);

	READ_DONE();
}

/*
 * _readFuncExpr
 */
static FuncExpr *
fc__readFuncExpr(void)
{
	READ_LOCALS(FuncExpr);

	READ_OID_FIELD(funcid);
	READ_OID_FIELD(funcresulttype);
	READ_BOOL_FIELD(funcretset);
	READ_BOOL_FIELD(funcvariadic);
	READ_ENUM_FIELD(funcformat, CoercionForm);
	READ_OID_FIELD(funccollid);
	READ_OID_FIELD(inputcollid);
	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readNamedArgExpr
 */
static NamedArgExpr *
fc__readNamedArgExpr(void)
{
	READ_LOCALS(NamedArgExpr);

	READ_NODE_FIELD(arg);
	READ_STRING_FIELD(name);
	READ_INT_FIELD(argnumber);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readOpExpr
 */
static OpExpr *
fc__readOpExpr(void)
{
	READ_LOCALS(OpExpr);

	READ_OID_FIELD(opno);
	READ_OID_FIELD(opfuncid);
	READ_OID_FIELD(opresulttype);
	READ_BOOL_FIELD(opretset);
	READ_OID_FIELD(opcollid);
	READ_OID_FIELD(inputcollid);
	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readDistinctExpr
 */
static DistinctExpr *
fc__readDistinctExpr(void)
{
	READ_LOCALS(DistinctExpr);

	READ_OID_FIELD(opno);
	READ_OID_FIELD(opfuncid);
	READ_OID_FIELD(opresulttype);
	READ_BOOL_FIELD(opretset);
	READ_OID_FIELD(opcollid);
	READ_OID_FIELD(inputcollid);
	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readNullIfExpr
 */
static NullIfExpr *
fc__readNullIfExpr(void)
{
	READ_LOCALS(NullIfExpr);

	READ_OID_FIELD(opno);
	READ_OID_FIELD(opfuncid);
	READ_OID_FIELD(opresulttype);
	READ_BOOL_FIELD(opretset);
	READ_OID_FIELD(opcollid);
	READ_OID_FIELD(inputcollid);
	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readScalarArrayOpExpr
 */
static ScalarArrayOpExpr *
fc__readScalarArrayOpExpr(void)
{
	READ_LOCALS(ScalarArrayOpExpr);

	READ_OID_FIELD(opno);
	READ_OID_FIELD(opfuncid);
	READ_OID_FIELD(hashfuncid);
	READ_OID_FIELD(negfuncid);
	READ_BOOL_FIELD(useOr);
	READ_OID_FIELD(inputcollid);
	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readBoolExpr
 */
static BoolExpr *
fc__readBoolExpr(void)
{
	READ_LOCALS(BoolExpr);

	/* 自定义枚举表示法 */
	fc_token = pg_strtok(&fc_length); /* 跳过 :boolop */
	fc_token = pg_strtok(&fc_length); /* 获取字段值 */
	if (strncmp(fc_token, "and", 3) == 0)
		fc_local_node->boolop = AND_EXPR;
	else if (strncmp(fc_token, "or", 2) == 0)
		fc_local_node->boolop = OR_EXPR;
	else if (strncmp(fc_token, "not", 3) == 0)
		fc_local_node->boolop = NOT_EXPR;
	else
		elog(ERROR, "unrecognized boolop \"%.*s\"", fc_length, fc_token);

	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readSubLink
 */
static SubLink *
fc__readSubLink(void)
{
	READ_LOCALS(SubLink);

	READ_ENUM_FIELD(subLinkType, SubLinkType);
	READ_INT_FIELD(subLinkId);
	READ_NODE_FIELD(testexpr);
	READ_NODE_FIELD(operName);
	READ_NODE_FIELD(subselect);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readSubPlan 并不需要，因为它在存储规则中不存在。
 */

/*
 * _readFieldSelect
 */
static FieldSelect *
fc__readFieldSelect(void)
{
	READ_LOCALS(FieldSelect);

	READ_NODE_FIELD(arg);
	READ_INT_FIELD(fieldnum);
	READ_OID_FIELD(resulttype);
	READ_INT_FIELD(resulttypmod);
	READ_OID_FIELD(resultcollid);

	READ_DONE();
}

/*
 * _readFieldStore
 */
static FieldStore *
fc__readFieldStore(void)
{
	READ_LOCALS(FieldStore);

	READ_NODE_FIELD(arg);
	READ_NODE_FIELD(newvals);
	READ_NODE_FIELD(fieldnums);
	READ_OID_FIELD(resulttype);

	READ_DONE();
}

/*
 * _readRelabelType
 */
static RelabelType *
fc__readRelabelType(void)
{
	READ_LOCALS(RelabelType);

	READ_NODE_FIELD(arg);
	READ_OID_FIELD(resulttype);
	READ_INT_FIELD(resulttypmod);
	READ_OID_FIELD(resultcollid);
	READ_ENUM_FIELD(relabelformat, CoercionForm);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCoerceViaIO
 */
static CoerceViaIO *
fc__readCoerceViaIO(void)
{
	READ_LOCALS(CoerceViaIO);

	READ_NODE_FIELD(arg);
	READ_OID_FIELD(resulttype);
	READ_OID_FIELD(resultcollid);
	READ_ENUM_FIELD(coerceformat, CoercionForm);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readArrayCoerceExpr
 */
static ArrayCoerceExpr *
fc__readArrayCoerceExpr(void)
{
	READ_LOCALS(ArrayCoerceExpr);

	READ_NODE_FIELD(arg);
	READ_NODE_FIELD(elemexpr);
	READ_OID_FIELD(resulttype);
	READ_INT_FIELD(resulttypmod);
	READ_OID_FIELD(resultcollid);
	READ_ENUM_FIELD(coerceformat, CoercionForm);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readConvertRowtypeExpr
 */
static ConvertRowtypeExpr *
fc__readConvertRowtypeExpr(void)
{
	READ_LOCALS(ConvertRowtypeExpr);

	READ_NODE_FIELD(arg);
	READ_OID_FIELD(resulttype);
	READ_ENUM_FIELD(convertformat, CoercionForm);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCollateExpr
 */
static CollateExpr *
fc__readCollateExpr(void)
{
	READ_LOCALS(CollateExpr);

	READ_NODE_FIELD(arg);
	READ_OID_FIELD(collOid);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCaseExpr
 */
static CaseExpr *
fc__readCaseExpr(void)
{
	READ_LOCALS(CaseExpr);

	READ_OID_FIELD(casetype);
	READ_OID_FIELD(casecollid);
	READ_NODE_FIELD(arg);
	READ_NODE_FIELD(args);
	READ_NODE_FIELD(defresult);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCaseWhen
 */
static CaseWhen *
fc__readCaseWhen(void)
{
	READ_LOCALS(CaseWhen);

	READ_NODE_FIELD(expr);
	READ_NODE_FIELD(result);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCaseTestExpr
 */
static CaseTestExpr *
fc__readCaseTestExpr(void)
{
	READ_LOCALS(CaseTestExpr);

	READ_OID_FIELD(typeId);
	READ_INT_FIELD(typeMod);
	READ_OID_FIELD(collation);

	READ_DONE();
}

/*
 * _readArrayExpr
 */
static ArrayExpr *
fc__readArrayExpr(void)
{
	READ_LOCALS(ArrayExpr);

	READ_OID_FIELD(array_typeid);
	READ_OID_FIELD(array_collid);
	READ_OID_FIELD(element_typeid);
	READ_NODE_FIELD(elements);
	READ_BOOL_FIELD(multidims);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readRowExpr
 */
static RowExpr * fc__readRowExpr(void)
{
	READ_LOCALS(RowExpr);

	READ_NODE_FIELD(args);
	READ_OID_FIELD(row_typeid);
	READ_ENUM_FIELD(row_format, CoercionForm);
	READ_NODE_FIELD(colnames);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readRowCompareExpr
 */
static RowCompareExpr *
fc__readRowCompareExpr(void)
{
	READ_LOCALS(RowCompareExpr);

	READ_ENUM_FIELD(rctype, RowCompareType);
	READ_NODE_FIELD(opnos);
	READ_NODE_FIELD(opfamilies);
	READ_NODE_FIELD(inputcollids);
	READ_NODE_FIELD(largs);
	READ_NODE_FIELD(rargs);

	READ_DONE();
}

/*
 * _readCoalesceExpr
 */
static CoalesceExpr *
fc__readCoalesceExpr(void)
{
	READ_LOCALS(CoalesceExpr);

	READ_OID_FIELD(coalescetype);
	READ_OID_FIELD(coalescecollid);
	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readMinMaxExpr
 */
static MinMaxExpr *
fc__readMinMaxExpr(void)
{
	READ_LOCALS(MinMaxExpr);

	READ_OID_FIELD(minmaxtype);
	READ_OID_FIELD(minmaxcollid);
	READ_OID_FIELD(inputcollid);
	READ_ENUM_FIELD(op, MinMaxOp);
	READ_NODE_FIELD(args);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readSQLValueFunction
 */
static SQLValueFunction *
fc__readSQLValueFunction(void)
{
	READ_LOCALS(SQLValueFunction);

	READ_ENUM_FIELD(op, SQLValueFunctionOp);
	READ_OID_FIELD(type);
	READ_INT_FIELD(typmod);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readXmlExpr
 */
static XmlExpr *
fc__readXmlExpr(void)
{
	READ_LOCALS(XmlExpr);

	READ_ENUM_FIELD(op, XmlExprOp);
	READ_STRING_FIELD(name);
	READ_NODE_FIELD(named_args);
	READ_NODE_FIELD(arg_names);
	READ_NODE_FIELD(args);
	READ_ENUM_FIELD(xmloption, XmlOptionType);
	READ_OID_FIELD(type);
	READ_INT_FIELD(typmod);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readNullTest
 */
static NullTest *
fc__readNullTest(void)
{
	READ_LOCALS(NullTest);

	READ_NODE_FIELD(arg);
	READ_ENUM_FIELD(nulltesttype, NullTestType);
	READ_BOOL_FIELD(argisrow);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readBooleanTest
 */
static BooleanTest *
fc__readBooleanTest(void)
{
	READ_LOCALS(BooleanTest);

	READ_NODE_FIELD(arg);
	READ_ENUM_FIELD(booltesttype, BoolTestType);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCoerceToDomain
 */
static CoerceToDomain *
fc__readCoerceToDomain(void)
{
	READ_LOCALS(CoerceToDomain);

	READ_NODE_FIELD(arg);
	READ_OID_FIELD(resulttype);
	READ_INT_FIELD(resulttypmod);
	READ_OID_FIELD(resultcollid);
	READ_ENUM_FIELD(coercionformat, CoercionForm);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCoerceToDomainValue
 */
static CoerceToDomainValue *
fc__readCoerceToDomainValue(void)
{
	READ_LOCALS(CoerceToDomainValue);

	READ_OID_FIELD(typeId);
	READ_INT_FIELD(typeMod);
	READ_OID_FIELD(collation);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readSetToDefault
 */
static SetToDefault *
fc__readSetToDefault(void)
{
	READ_LOCALS(SetToDefault);

	READ_OID_FIELD(typeId);
	READ_INT_FIELD(typeMod);
	READ_OID_FIELD(collation);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readCurrentOfExpr
 */
static CurrentOfExpr *
fc__readCurrentOfExpr(void)
{
	READ_LOCALS(CurrentOfExpr);

	READ_UINT_FIELD(cvarno);
	READ_STRING_FIELD(cursor_name);
	READ_INT_FIELD(cursor_param);

	READ_DONE();
}

/*
 * _readNextValueExpr
 */
static NextValueExpr *
fc__readNextValueExpr(void)
{
	READ_LOCALS(NextValueExpr);

	READ_OID_FIELD(seqid);
	READ_OID_FIELD(typeId);

	READ_DONE();
}

/*
 * _readInferenceElem
 */
static InferenceElem *
fc__readInferenceElem(void)
{
	READ_LOCALS(InferenceElem);

	READ_NODE_FIELD(expr);
	READ_OID_FIELD(infercollid);
	READ_OID_FIELD(inferopclass);

	READ_DONE();
}

/*
 * _readTargetEntry
 */
static TargetEntry * fc__readTargetEntry(void)
{
	READ_LOCALS(TargetEntry);

	READ_NODE_FIELD(expr);
	READ_INT_FIELD(resno);
	READ_STRING_FIELD(resname);
	READ_UINT_FIELD(ressortgroupref);
	READ_OID_FIELD(resorigtbl);
	READ_INT_FIELD(resorigcol);
	READ_BOOL_FIELD(resjunk);

	READ_DONE();
}

/*
 * _readRangeTblRef
 */
static RangeTblRef *
fc__readRangeTblRef(void)
{
	READ_LOCALS(RangeTblRef);

	READ_INT_FIELD(rtindex);

	READ_DONE();
}

/*
 * _readJoinExpr
 */
static JoinExpr *
fc__readJoinExpr(void)
{
	READ_LOCALS(JoinExpr);

	READ_ENUM_FIELD(jointype, JoinType);
	READ_BOOL_FIELD(isNatural);
	READ_NODE_FIELD(larg);
	READ_NODE_FIELD(rarg);
	READ_NODE_FIELD(usingClause);
	READ_NODE_FIELD(join_using_alias);
	READ_NODE_FIELD(quals);
	READ_NODE_FIELD(alias);
	READ_INT_FIELD(rtindex);

	READ_DONE();
}

/*
 * _readFromExpr
 */
static FromExpr *
fc__readFromExpr(void)
{
	READ_LOCALS(FromExpr);

	READ_NODE_FIELD(fromlist);
	READ_NODE_FIELD(quals);

	READ_DONE();
}

/*
 * _readOnConflictExpr
 */
static OnConflictExpr * fc__readOnConflictExpr(void)
{
	READ_LOCALS(OnConflictExpr);

	READ_ENUM_FIELD(action, OnConflictAction);
	READ_NODE_FIELD(arbiterElems);
	READ_NODE_FIELD(arbiterWhere);
	READ_OID_FIELD(constraint);
	READ_NODE_FIELD(onConflictSet);
	READ_NODE_FIELD(onConflictWhere);
	READ_INT_FIELD(exclRelIndex);
	READ_NODE_FIELD(exclRelTlist);

	READ_DONE();
}

/*
 * 来自 pathnodes.h 的内容。
 *
 * 我们通常不需要再次读取规划器节点，但其中一些
 * 也会出现在计划树中。
 */

/*
 * _readAppendRelInfo
 */
static AppendRelInfo *
fc__readAppendRelInfo(void)
{
	READ_LOCALS(AppendRelInfo);

	READ_UINT_FIELD(parent_relid);
	READ_UINT_FIELD(child_relid);
	READ_OID_FIELD(parent_reltype);
	READ_OID_FIELD(child_reltype);
	READ_NODE_FIELD(translated_vars);
	READ_INT_FIELD(num_child_cols);
	READ_ATTRNUMBER_ARRAY(parent_colnos, fc_local_node->num_child_cols);
	READ_OID_FIELD(parent_reloid);

	READ_DONE();
}

/*
 * 来自 parsenodes.h 的内容。
 */

/*
 * _readRangeTblEntry
 */
static RangeTblEntry * fc__readRangeTblEntry(void)
{
	READ_LOCALS(RangeTblEntry);

	/* 将别名 + eref 放在首位以使转储更加清晰 */
	READ_NODE_FIELD(alias);
	READ_NODE_FIELD(eref);
	READ_ENUM_FIELD(rtekind, RTEKind);

	switch (fc_local_node->rtekind)
	{
		case RTE_RELATION:
			READ_OID_FIELD(relid);
			READ_CHAR_FIELD(relkind);
			READ_INT_FIELD(rellockmode);
			READ_NODE_FIELD(tablesample);
			break;
		case RTE_SUBQUERY:
			READ_NODE_FIELD(subquery);
			READ_BOOL_FIELD(security_barrier);
			break;
		case RTE_JOIN:
			READ_ENUM_FIELD(jointype, JoinType);
			READ_INT_FIELD(joinmergedcols);
			READ_NODE_FIELD(joinaliasvars);
			READ_NODE_FIELD(joinleftcols);
			READ_NODE_FIELD(joinrightcols);
			READ_NODE_FIELD(join_using_alias);
			break;
		case RTE_FUNCTION:
			READ_NODE_FIELD(functions);
			READ_BOOL_FIELD(funcordinality);
			break;
		case RTE_TABLEFUNC:
			READ_NODE_FIELD(tablefunc);
			/* RTE 必须有列类型信息的副本（如果有） */
			if (fc_local_node->tablefunc)
			{
				TableFunc  *fc_tf = fc_local_node->tablefunc;

				fc_local_node->coltypes = fc_tf->coltypes;
				fc_local_node->coltypmods = fc_tf->coltypmods;
				fc_local_node->colcollations = fc_tf->colcollations;
			}
			break;
		case RTE_VALUES:
			READ_NODE_FIELD(values_lists);
			READ_NODE_FIELD(coltypes);
			READ_NODE_FIELD(coltypmods);
			READ_NODE_FIELD(colcollations);
			break;
		case RTE_CTE:
			READ_STRING_FIELD(ctename);
			READ_UINT_FIELD(ctelevelsup);
			READ_BOOL_FIELD(self_reference);
			READ_NODE_FIELD(coltypes);
			READ_NODE_FIELD(coltypmods);
			READ_NODE_FIELD(colcollations);
			break;
		case RTE_NAMEDTUPLESTORE:
			READ_STRING_FIELD(enrname);
			READ_FLOAT_FIELD(enrtuples);
			READ_OID_FIELD(relid);
			READ_NODE_FIELD(coltypes);
			READ_NODE_FIELD(coltypmods);
			READ_NODE_FIELD(colcollations);
			break;
		case RTE_RESULT:
			/* 没有额外的字段 */
			break;
		default:
			elog(ERROR, "unrecognized RTE kind: %d",
				 (int) fc_local_node->rtekind);
			break;
	}

	READ_BOOL_FIELD(lateral);
	READ_BOOL_FIELD(inh);
	READ_BOOL_FIELD(inFromCl);
	READ_UINT_FIELD(requiredPerms);
	READ_OID_FIELD(checkAsUser);
	READ_BITMAPSET_FIELD(selectedCols);
	READ_BITMAPSET_FIELD(insertedCols);
	READ_BITMAPSET_FIELD(updatedCols);
	READ_BITMAPSET_FIELD(extraUpdatedCols);
	READ_NODE_FIELD(securityQuals);

	READ_DONE();
}

/*
 * _readRangeTblFunction
 */
static RangeTblFunction *
fc__readRangeTblFunction(void)
{
	READ_LOCALS(RangeTblFunction);

	READ_NODE_FIELD(funcexpr);
	READ_INT_FIELD(funccolcount);
	READ_NODE_FIELD(funccolnames);
	READ_NODE_FIELD(funccoltypes);
	READ_NODE_FIELD(funccoltypmods);
	READ_NODE_FIELD(funccolcollations);
	READ_BITMAPSET_FIELD(funcparams);

	READ_DONE();
}

/*
 * _readTableSampleClause
 */
static TableSampleClause * fc__readTableSampleClause(void)
{
	READ_LOCALS(TableSampleClause);

	READ_OID_FIELD(tsmhandler);
	READ_NODE_FIELD(args);
	READ_NODE_FIELD(repeatable);

	READ_DONE();
}

/*
 * _readDefElem
 */
static DefElem * fc__readDefElem(void)
{
	READ_LOCALS(DefElem);

	READ_STRING_FIELD(defnamespace);
	READ_STRING_FIELD(defname);
	READ_NODE_FIELD(arg);
	READ_ENUM_FIELD(defaction, DefElemAction);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * 来自 plannodes.h 的内容。
 */

/*
 * _readPlannedStmt
 */
static PlannedStmt * fc__readPlannedStmt(void)
{
	READ_LOCALS(PlannedStmt);

	READ_ENUM_FIELD(commandType, CmdType);
	READ_UINT64_FIELD(queryId);
	READ_BOOL_FIELD(hasReturning);
	READ_BOOL_FIELD(hasModifyingCTE);
	READ_BOOL_FIELD(canSetTag);
	READ_BOOL_FIELD(transientPlan);
	READ_BOOL_FIELD(dependsOnRole);
	READ_BOOL_FIELD(parallelModeNeeded);
	READ_INT_FIELD(jitFlags);
	READ_NODE_FIELD(planTree);
	READ_NODE_FIELD(rtable);
	READ_NODE_FIELD(resultRelations);
	READ_NODE_FIELD(appendRelations);
	READ_NODE_FIELD(subplans);
	READ_BITMAPSET_FIELD(rewindPlanIDs);
	READ_NODE_FIELD(rowMarks);
	READ_NODE_FIELD(relationOids);
	READ_NODE_FIELD(invalItems);
	READ_NODE_FIELD(paramExecTypes);
	READ_NODE_FIELD(utilityStmt);
	READ_LOCATION_FIELD(stmt_location);
	READ_INT_FIELD(stmt_len);

	READ_DONE();
}

/*
 * ReadCommonPlan
 *	为所有从 Plan 继承的节点分配基本内容
 */
static void fc_ReadCommonPlan(Plan *fc_local_node)
{
	READ_TEMP_LOCALS();

	READ_FLOAT_FIELD(startup_cost);
	READ_FLOAT_FIELD(total_cost);
	READ_FLOAT_FIELD(plan_rows);
	READ_INT_FIELD(plan_width);
	READ_BOOL_FIELD(parallel_aware);
	READ_BOOL_FIELD(parallel_safe);
	READ_BOOL_FIELD(async_capable);
	READ_INT_FIELD(plan_node_id);
	READ_NODE_FIELD(targetlist);
	READ_NODE_FIELD(qual);
	READ_NODE_FIELD(lefttree);
	READ_NODE_FIELD(righttree);
	READ_NODE_FIELD(initPlan);
	READ_BITMAPSET_FIELD(extParam);
	READ_BITMAPSET_FIELD(allParam);
}

/*
 * _readPlan
 */
static Plan * fc__readPlan(void)
{
	READ_LOCALS_NO_FIELDS(Plan);

	fc_ReadCommonPlan(fc_local_node);

	READ_DONE();
}

/*
 * _readResult
 */
static Result * fc__readResult(void)
{
	READ_LOCALS(Result);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_NODE_FIELD(resconstantqual);

	READ_DONE();
}

/*
 * _readProjectSet
 */
static ProjectSet * fc__readProjectSet(void)
{
	READ_LOCALS_NO_FIELDS(ProjectSet);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_DONE();
}

/*
 * _readModifyTable
 */
static ModifyTable * fc__readModifyTable(void)
{
	READ_LOCALS(ModifyTable);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_ENUM_FIELD(operation, CmdType);
	READ_BOOL_FIELD(canSetTag);
	READ_UINT_FIELD(nominalRelation);
	READ_UINT_FIELD(rootRelation);
	READ_BOOL_FIELD(partColsUpdated);
	READ_NODE_FIELD(resultRelations);
	READ_NODE_FIELD(updateColnosLists);
	READ_NODE_FIELD(withCheckOptionLists);
	READ_NODE_FIELD(returningLists);
	READ_NODE_FIELD(fdwPrivLists);
	READ_BITMAPSET_FIELD(fdwDirectModifyPlans);
	READ_NODE_FIELD(rowMarks);
	READ_INT_FIELD(epqParam);
	READ_ENUM_FIELD(onConflictAction, OnConflictAction);
	READ_NODE_FIELD(arbiterIndexes);
	READ_NODE_FIELD(onConflictSet);
	READ_NODE_FIELD(onConflictCols);
	READ_NODE_FIELD(onConflictWhere);
	READ_UINT_FIELD(exclRelRTI);
	READ_NODE_FIELD(exclRelTlist);
	READ_NODE_FIELD(mergeActionLists);

	READ_DONE();
}

/*
 * _readAppend
 */
static Append *
fc__readAppend(void)
{
	READ_LOCALS(Append);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_BITMAPSET_FIELD(apprelids);
	READ_NODE_FIELD(appendplans);
	READ_INT_FIELD(nasyncplans);
	READ_INT_FIELD(first_partial_plan);
	READ_NODE_FIELD(part_prune_info);

	READ_DONE();
}

/*
 * _readMergeAppend
 */
static MergeAppend *
fc__readMergeAppend(void)
{
	READ_LOCALS(MergeAppend);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_BITMAPSET_FIELD(apprelids);
	READ_NODE_FIELD(mergeplans);
	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(sortColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(sortOperators, fc_local_node->numCols);
	READ_OID_ARRAY(collations, fc_local_node->numCols);
	READ_BOOL_ARRAY(nullsFirst, fc_local_node->numCols);
	READ_NODE_FIELD(part_prune_info);

	READ_DONE();
}

/*
 * _readRecursiveUnion
 */
static RecursiveUnion * fc__readRecursiveUnion(void)
{
	READ_LOCALS(RecursiveUnion);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_INT_FIELD(wtParam);
	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(dupColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(dupOperators, fc_local_node->numCols);
	READ_OID_ARRAY(dupCollations, fc_local_node->numCols);
	READ_LONG_FIELD(numGroups);

	READ_DONE();
}

/*
 * _readBitmapAnd
 */
static BitmapAnd * fc__readBitmapAnd(void)
{
	READ_LOCALS(BitmapAnd);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_NODE_FIELD(bitmapplans);

	READ_DONE();
}

/*
 * _readBitmapOr
 */
static BitmapOr * fc__readBitmapOr(void)
{
	READ_LOCALS(BitmapOr);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_BOOL_FIELD(isshared);
	READ_NODE_FIELD(bitmapplans);

	READ_DONE();
}

/*
 * ReadCommonScan
 *	为所有从 Scan 继承的节点分配基本内容
 */
static void fc_ReadCommonScan(Scan *fc_local_node)
{
	READ_TEMP_LOCALS();

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_UINT_FIELD(scanrelid);
}

/*
 * _readScan
 */
static Scan * fc__readScan(void)
{
	READ_LOCALS_NO_FIELDS(Scan);

	fc_ReadCommonScan(fc_local_node);

	READ_DONE();
}

/*
 * _readSeqScan
 */
static SeqScan * fc__readSeqScan(void)
{
	READ_LOCALS_NO_FIELDS(SeqScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_DONE();
}

/*
 * _readSampleScan
 */
static SampleScan * fc__readSampleScan(void)
{
	READ_LOCALS(SampleScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(tablesample);

	READ_DONE();
}

/*
 * _readIndexScan
 */
static IndexScan * fc__readIndexScan(void)
{
	READ_LOCALS(IndexScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_OID_FIELD(indexid);
	READ_NODE_FIELD(indexqual);
	READ_NODE_FIELD(indexqualorig);
	READ_NODE_FIELD(indexorderby);
	READ_NODE_FIELD(indexorderbyorig);
	READ_NODE_FIELD(indexorderbyops);
	READ_ENUM_FIELD(indexorderdir, ScanDirection);

	READ_DONE();
}

/*
 * _readIndexOnlyScan
 */
static IndexOnlyScan * fc__readIndexOnlyScan(void)
{
	READ_LOCALS(IndexOnlyScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_OID_FIELD(indexid);
	READ_NODE_FIELD(indexqual);
	READ_NODE_FIELD(recheckqual);
	READ_NODE_FIELD(indexorderby);
	READ_NODE_FIELD(indextlist);
	READ_ENUM_FIELD(indexorderdir, ScanDirection);

	READ_DONE();
}

/*
 * _readBitmapIndexScan
 */
static BitmapIndexScan * fc__readBitmapIndexScan(void)
{
	READ_LOCALS(BitmapIndexScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_OID_FIELD(indexid);
	READ_BOOL_FIELD(isshared);
	READ_NODE_FIELD(indexqual);
	READ_NODE_FIELD(indexqualorig);

	READ_DONE();
}

/*
 * _读取位图堆扫描
 */
static BitmapHeapScan * fc__readBitmapHeapScan(void)
{
	READ_LOCALS(BitmapHeapScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(bitmapqualorig);

	READ_DONE();
}

/*
 * _读取Tid扫描
 */
static TidScan * fc__readTidScan(void)
{
	READ_LOCALS(TidScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(tidquals);

	READ_DONE();
}

/*
 * _读取Tid范围扫描
 */
static TidRangeScan * fc__readTidRangeScan(void)
{
	READ_LOCALS(TidRangeScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(tidrangequals);

	READ_DONE();
}

/*
 * _读取子查询扫描
 */
static SubqueryScan * fc__readSubqueryScan(void)
{
	READ_LOCALS(SubqueryScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(subplan);
	READ_ENUM_FIELD(scanstatus, SubqueryScanStatus);

	READ_DONE();
}

/*
 * _读取函数扫描
 */
static FunctionScan * fc__readFunctionScan(void)
{
	READ_LOCALS(FunctionScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(functions);
	READ_BOOL_FIELD(funcordinality);

	READ_DONE();
}

/*
 * _读取值扫描
 */
static ValuesScan * fc__readValuesScan(void)
{
	READ_LOCALS(ValuesScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(values_lists);

	READ_DONE();
}

/*
 * _读取表函数扫描
 */
static TableFuncScan * fc__readTableFuncScan(void)
{
	READ_LOCALS(TableFuncScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_NODE_FIELD(tablefunc);

	READ_DONE();
}

/*
 * _读取公共表达式扫描
 */
static CteScan * fc__readCteScan(void)
{
	READ_LOCALS(CteScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_INT_FIELD(ctePlanId);
	READ_INT_FIELD(cteParam);

	READ_DONE();
}

/*
 * _读取命名元组存储扫描
 */
static NamedTuplestoreScan * fc__readNamedTuplestoreScan(void)
{
	READ_LOCALS(NamedTuplestoreScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_STRING_FIELD(enrname);

	READ_DONE();
}

/*
 * _读取工作表扫描
 */
static WorkTableScan * fc__readWorkTableScan(void)
{
	READ_LOCALS(WorkTableScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_INT_FIELD(wtParam);

	READ_DONE();
}

/*
 * _读取外部扫描
 */
static ForeignScan * fc__readForeignScan(void)
{
	READ_LOCALS(ForeignScan);

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_ENUM_FIELD(operation, CmdType);
	READ_UINT_FIELD(resultRelation);
	READ_OID_FIELD(fs_server);
	READ_NODE_FIELD(fdw_exprs);
	READ_NODE_FIELD(fdw_private);
	READ_NODE_FIELD(fdw_scan_tlist);
	READ_NODE_FIELD(fdw_recheck_quals);
	READ_BITMAPSET_FIELD(fs_relids);
	READ_BOOL_FIELD(fsSystemCol);

	READ_DONE();
}

/*
 * _读取自定义扫描
 */
static CustomScan * fc__readCustomScan(void)
{
	READ_LOCALS(CustomScan);
	char	   *fc_custom_name;
	const CustomScanMethods *fc_methods;

	fc_ReadCommonScan(&fc_local_node->scan);

	READ_UINT_FIELD(flags);
	READ_NODE_FIELD(custom_plans);
	READ_NODE_FIELD(custom_exprs);
	READ_NODE_FIELD(custom_private);
	READ_NODE_FIELD(custom_scan_tlist);
	READ_BITMAPSET_FIELD(custom_relids);

	/* 通过CustomName查找CustomScanMethods */
	fc_token = pg_strtok(&fc_length); /* 跳过的方法: */
	fc_token = pg_strtok(&fc_length); /* CustomName */
	fc_custom_name = nullable_string(fc_token, fc_length);
	fc_methods = GetCustomScanMethods(fc_custom_name, false);
	fc_local_node->methods = fc_methods;

	READ_DONE();
}

/*
 * 读取公共连接
 *	分配所有继承自Join节点的基本内容
 */
static void fc_ReadCommonJoin(Join *fc_local_node)
{
	READ_TEMP_LOCALS();

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_ENUM_FIELD(jointype, JoinType);
	READ_BOOL_FIELD(inner_unique);
	READ_NODE_FIELD(joinqual);
}

/*
 * _读取连接
 */
static Join *
fc__readJoin(void)
{
	READ_LOCALS_NO_FIELDS(Join);

	fc_ReadCommonJoin(fc_local_node);

	READ_DONE();
}

/*
 * _读取嵌套循环
 */
static NestLoop * fc__readNestLoop(void)
{
	READ_LOCALS(NestLoop);

	fc_ReadCommonJoin(&fc_local_node->join);

	READ_NODE_FIELD(nestParams);

	READ_DONE();
}

/*
 * _读取合并连接
 */
static MergeJoin * fc__readMergeJoin(void)
{
	int			fc_numCols;

	READ_LOCALS(MergeJoin);

	fc_ReadCommonJoin(&fc_local_node->join);

	READ_BOOL_FIELD(skip_mark_restore);
	READ_NODE_FIELD(mergeclauses);

	fc_numCols = list_length(fc_local_node->mergeclauses);

	READ_OID_ARRAY(mergeFamilies, fc_numCols);
	READ_OID_ARRAY(mergeCollations, fc_numCols);
	READ_INT_ARRAY(mergeStrategies, fc_numCols);
	READ_BOOL_ARRAY(mergeNullsFirst, fc_numCols);

	READ_DONE();
}

/*
 * _读取哈希连接
 */
static HashJoin * fc__readHashJoin(void)
{
	READ_LOCALS(HashJoin);

	fc_ReadCommonJoin(&fc_local_node->join);

	READ_NODE_FIELD(hashclauses);
	READ_NODE_FIELD(hashoperators);
	READ_NODE_FIELD(hashcollations);
	READ_NODE_FIELD(hashkeys);

	READ_DONE();
}

/*
 * _读取材料
 */
static Material * fc__readMaterial(void)
{
	READ_LOCALS_NO_FIELDS(Material);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_DONE();
}

/*
 * _读取记忆
 */
static Memoize * fc__readMemoize(void)
{
	READ_LOCALS(Memoize);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_INT_FIELD(numKeys);
	READ_OID_ARRAY(hashOperators, fc_local_node->numKeys);
	READ_OID_ARRAY(collations, fc_local_node->numKeys);
	READ_NODE_FIELD(param_exprs);
	READ_BOOL_FIELD(singlerow);
	READ_BOOL_FIELD(binary_mode);
	READ_UINT_FIELD(est_entries);
	READ_BITMAPSET_FIELD(keyparamids);

	READ_DONE();
}

/*
 * 读取公共排序
 *	分配所有继承自Sort节点的基本内容
 */
static void fc_ReadCommonSort(Sort *fc_local_node)
{
	READ_TEMP_LOCALS();

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(sortColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(sortOperators, fc_local_node->numCols);
	READ_OID_ARRAY(collations, fc_local_node->numCols);
	READ_BOOL_ARRAY(nullsFirst, fc_local_node->numCols);
}

/*
 * _读取排序
 */
static Sort * fc__readSort(void)
{
	READ_LOCALS_NO_FIELDS(Sort);

	fc_ReadCommonSort(fc_local_node);

	READ_DONE();
}

/*
 * _读取增量排序
 */
static IncrementalSort * fc__readIncrementalSort(void)
{
	READ_LOCALS(IncrementalSort);

	fc_ReadCommonSort(&fc_local_node->sort);

	READ_INT_FIELD(nPresortedCols);

	READ_DONE();
}

/*
 * _读取分组
 */
static Group * fc__readGroup(void)
{
	READ_LOCALS(Group);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(grpColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(grpOperators, fc_local_node->numCols);
	READ_OID_ARRAY(grpCollations, fc_local_node->numCols);

	READ_DONE();
}

/*
 * _读取聚合
 */
static Agg * fc__readAgg(void)
{
	READ_LOCALS(Agg);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_ENUM_FIELD(aggstrategy, AggStrategy);
	READ_ENUM_FIELD(aggsplit, AggSplit);
	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(grpColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(grpOperators, fc_local_node->numCols);
	READ_OID_ARRAY(grpCollations, fc_local_node->numCols);
	READ_LONG_FIELD(numGroups);
	READ_UINT64_FIELD(transitionSpace);
	READ_BITMAPSET_FIELD(aggParams);
	READ_NODE_FIELD(groupingSets);
	READ_NODE_FIELD(chain);

	READ_DONE();
}

/*
 * _读取窗口聚合
 */
static WindowAgg * fc__readWindowAgg(void)
{
	READ_LOCALS(WindowAgg);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_UINT_FIELD(winref);
	READ_INT_FIELD(partNumCols);
	READ_ATTRNUMBER_ARRAY(partColIdx, fc_local_node->partNumCols);
	READ_OID_ARRAY(partOperators, fc_local_node->partNumCols);
	READ_OID_ARRAY(partCollations, fc_local_node->partNumCols);
	READ_INT_FIELD(ordNumCols);
	READ_ATTRNUMBER_ARRAY(ordColIdx, fc_local_node->ordNumCols);
	READ_OID_ARRAY(ordOperators, fc_local_node->ordNumCols);
	READ_OID_ARRAY(ordCollations, fc_local_node->ordNumCols);
	READ_INT_FIELD(frameOptions);
	READ_NODE_FIELD(startOffset);
	READ_NODE_FIELD(endOffset);
	READ_NODE_FIELD(runCondition);
	READ_NODE_FIELD(runConditionOrig);
	READ_OID_FIELD(startInRangeFunc);
	READ_OID_FIELD(endInRangeFunc);
	READ_OID_FIELD(inRangeColl);
	READ_BOOL_FIELD(inRangeAsc);
	READ_BOOL_FIELD(inRangeNullsFirst);
	READ_BOOL_FIELD(topWindow);

	READ_DONE();
}

/*
 * _读取唯一
 */
static Unique * fc__readUnique(void)
{
	READ_LOCALS(Unique);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(uniqColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(uniqOperators, fc_local_node->numCols);
	READ_OID_ARRAY(uniqCollations, fc_local_node->numCols);

	READ_DONE();
}

/*
 * _读取收集
 */
static Gather * fc__readGather(void)
{
	READ_LOCALS(Gather);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_INT_FIELD(num_workers);
	READ_INT_FIELD(rescan_param);
	READ_BOOL_FIELD(single_copy);
	READ_BOOL_FIELD(invisible);
	READ_BITMAPSET_FIELD(initParam);

	READ_DONE();
}

/*
 * _readGatherMerge
 */
static GatherMerge * fc__readGatherMerge(void)
{
	READ_LOCALS(GatherMerge);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_INT_FIELD(num_workers);
	READ_INT_FIELD(rescan_param);
	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(sortColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(sortOperators, fc_local_node->numCols);
	READ_OID_ARRAY(collations, fc_local_node->numCols);
	READ_BOOL_ARRAY(nullsFirst, fc_local_node->numCols);
	READ_BITMAPSET_FIELD(initParam);

	READ_DONE();
}

/*
 * _readHash
 */
static Hash * fc__readHash(void)
{
	READ_LOCALS(Hash);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_NODE_FIELD(hashkeys);
	READ_OID_FIELD(skewTable);
	READ_INT_FIELD(skewColumn);
	READ_BOOL_FIELD(skewInherit);
	READ_FLOAT_FIELD(rows_total);

	READ_DONE();
}

/*
 * _readSetOp
 */
static SetOp * fc__readSetOp(void)
{
	READ_LOCALS(SetOp);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_ENUM_FIELD(cmd, SetOpCmd);
	READ_ENUM_FIELD(strategy, SetOpStrategy);
	READ_INT_FIELD(numCols);
	READ_ATTRNUMBER_ARRAY(dupColIdx, fc_local_node->numCols);
	READ_OID_ARRAY(dupOperators, fc_local_node->numCols);
	READ_OID_ARRAY(dupCollations, fc_local_node->numCols);
	READ_INT_FIELD(flagColIdx);
	READ_INT_FIELD(firstFlag);
	READ_LONG_FIELD(numGroups);

	READ_DONE();
}

/*
 * _readLockRows
 */
static LockRows * fc__readLockRows(void)
{
	READ_LOCALS(LockRows);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_NODE_FIELD(rowMarks);
	READ_INT_FIELD(epqParam);

	READ_DONE();
}

/*
 * _readLimit
 */
static Limit * fc__readLimit(void)
{
	READ_LOCALS(Limit);

	fc_ReadCommonPlan(&fc_local_node->plan);

	READ_NODE_FIELD(limitOffset);
	READ_NODE_FIELD(limitCount);
	READ_ENUM_FIELD(limitOption, LimitOption);
	READ_INT_FIELD(uniqNumCols);
	READ_ATTRNUMBER_ARRAY(uniqColIdx, fc_local_node->uniqNumCols);
	READ_OID_ARRAY(uniqOperators, fc_local_node->uniqNumCols);
	READ_OID_ARRAY(uniqCollations, fc_local_node->uniqNumCols);

	READ_DONE();
}

/*
 * _readNestLoopParam
 */
static NestLoopParam *
fc__readNestLoopParam(void)
{
	READ_LOCALS(NestLoopParam);

	READ_INT_FIELD(paramno);
	READ_NODE_FIELD(paramval);

	READ_DONE();
}

/*
 * _readPlanRowMark
 */
static PlanRowMark *
fc__readPlanRowMark(void)
{
	READ_LOCALS(PlanRowMark);

	READ_UINT_FIELD(rti);
	READ_UINT_FIELD(prti);
	READ_UINT_FIELD(rowmarkId);
	READ_ENUM_FIELD(markType, RowMarkType);
	READ_INT_FIELD(allMarkTypes);
	READ_ENUM_FIELD(strength, LockClauseStrength);
	READ_ENUM_FIELD(waitPolicy, LockWaitPolicy);
	READ_BOOL_FIELD(isParent);

	READ_DONE();
}

static PartitionPruneInfo *
fc__readPartitionPruneInfo(void)
{
	READ_LOCALS(PartitionPruneInfo);

	READ_NODE_FIELD(prune_infos);
	READ_BITMAPSET_FIELD(other_subplans);

	READ_DONE();
}

static PartitionedRelPruneInfo *
fc__readPartitionedRelPruneInfo(void)
{
	READ_LOCALS(PartitionedRelPruneInfo);

	READ_UINT_FIELD(rtindex);
	READ_BITMAPSET_FIELD(present_parts);
	READ_INT_FIELD(nparts);
	READ_INT_ARRAY(subplan_map, fc_local_node->nparts);
	READ_INT_ARRAY(subpart_map, fc_local_node->nparts);
	READ_OID_ARRAY(relid_map, fc_local_node->nparts);
	READ_NODE_FIELD(initial_pruning_steps);
	READ_NODE_FIELD(exec_pruning_steps);
	READ_BITMAPSET_FIELD(execparamids);

	READ_DONE();
}

static PartitionPruneStepOp *
fc__readPartitionPruneStepOp(void)
{
	READ_LOCALS(PartitionPruneStepOp);

	READ_INT_FIELD(step.step_id);
	READ_INT_FIELD(opstrategy);
	READ_NODE_FIELD(exprs);
	READ_NODE_FIELD(cmpfns);
	READ_BITMAPSET_FIELD(nullkeys);

	READ_DONE();
}

static PartitionPruneStepCombine *
fc__readPartitionPruneStepCombine(void)
{
	READ_LOCALS(PartitionPruneStepCombine);

	READ_INT_FIELD(step.step_id);
	READ_ENUM_FIELD(combineOp, PartitionPruneCombineOp);
	READ_NODE_FIELD(source_stepids);

	READ_DONE();
}

/*
 * _readPlanInvalItem
 */
static PlanInvalItem *
fc__readPlanInvalItem(void)
{
	READ_LOCALS(PlanInvalItem);

	READ_INT_FIELD(cacheId);
	READ_UINT_FIELD(hashValue);

	READ_DONE();
}

/*
 * _readSubPlan
 */
static SubPlan *
fc__readSubPlan(void)
{
	READ_LOCALS(SubPlan);

	READ_ENUM_FIELD(subLinkType, SubLinkType);
	READ_NODE_FIELD(testexpr);
	READ_NODE_FIELD(paramIds);
	READ_INT_FIELD(plan_id);
	READ_STRING_FIELD(plan_name);
	READ_OID_FIELD(firstColType);
	READ_INT_FIELD(firstColTypmod);
	READ_OID_FIELD(firstColCollation);
	READ_BOOL_FIELD(useHashTable);
	READ_BOOL_FIELD(unknownEqFalse);
	READ_BOOL_FIELD(parallel_safe);
	READ_NODE_FIELD(setParam);
	READ_NODE_FIELD(parParam);
	READ_NODE_FIELD(args);
	READ_FLOAT_FIELD(startup_cost);
	READ_FLOAT_FIELD(per_call_cost);

	READ_DONE();
}

/*
 * _readAlternativeSubPlan
 */
static AlternativeSubPlan *
fc__readAlternativeSubPlan(void)
{
	READ_LOCALS(AlternativeSubPlan);

	READ_NODE_FIELD(subplans);

	READ_DONE();
}

/*
 * _readExtensibleNode
 */
static ExtensibleNode *
fc__readExtensibleNode(void)
{
	const ExtensibleNodeMethods *fc_methods;
	ExtensibleNode *fc_local_node;
	const char *fc_extnodename;

	READ_TEMP_LOCALS();

	fc_token = pg_strtok(&fc_length); /* 跳过 :extnodename */
	fc_token = pg_strtok(&fc_length); /* 获取 extnodename */

	fc_extnodename = nullable_string(fc_token, fc_length);
	if (!fc_extnodename)
		elog(ERROR, "extnodename has to be supplied");
	fc_methods = GetExtensibleNodeMethods(fc_extnodename, false);

	fc_local_node = (ExtensibleNode *) newNode(fc_methods->node_size,
											T_ExtensibleNode);
	fc_local_node->extnodename = fc_extnodename;

	/* 反序列化私有字段 */
	fc_methods->nodeRead(fc_local_node);

	READ_DONE();
}

/*
 * _readPartitionBoundSpec
 */
static PartitionBoundSpec *
fc__readPartitionBoundSpec(void)
{
	READ_LOCALS(PartitionBoundSpec);

	READ_CHAR_FIELD(strategy);
	READ_BOOL_FIELD(is_default);
	READ_INT_FIELD(modulus);
	READ_INT_FIELD(remainder);
	READ_NODE_FIELD(listdatums);
	READ_NODE_FIELD(lowerdatums);
	READ_NODE_FIELD(upperdatums);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * _readPartitionRangeDatum
 */
static PartitionRangeDatum *
fc__readPartitionRangeDatum(void)
{
	READ_LOCALS(PartitionRangeDatum);

	READ_ENUM_FIELD(kind, PartitionRangeDatumKind);
	READ_NODE_FIELD(value);
	READ_LOCATION_FIELD(location);

	READ_DONE();
}

/*
 * parseNodeString
 *
 * 给定一个表示节点树的字符字符串，parseNodeString 创建
 * 内部节点结构。
 *
 * 要读取的字符串必须已经加载到 pg_strtok() 中。
 */
Node * parseNodeString(void)
{
	void	   *fc_return_value;

	READ_TEMP_LOCALS();

	/* 防止因过于复杂的表达式导致栈溢出 */
	check_stack_depth();

	fc_token = pg_strtok(&fc_length);

#define MATCH(tokname, namelen) \
	(fc_length == namelen && memcmp(fc_token, tokname, namelen) == 0)

	if (MATCH("QUERY", 5))
		fc_return_value = fc__readQuery();
	else if (MATCH("WITHCHECKOPTION", 15))
		fc_return_value = fc__readWithCheckOption();
	else if (MATCH("SORTGROUPCLAUSE", 15))
		fc_return_value = fc__readSortGroupClause();
	else if (MATCH("GROUPINGSET", 11))
		fc_return_value = fc__readGroupingSet();
	else if (MATCH("WINDOWCLAUSE", 12))
		fc_return_value = fc__readWindowClause();
	else if (MATCH("ROWMARKCLAUSE", 13))
		fc_return_value = fc__readRowMarkClause();
	else if (MATCH("CTESEARCHCLAUSE", 15))
		fc_return_value = fc__readCTESearchClause();
	else if (MATCH("CTECYCLECLAUSE", 14))
		fc_return_value = fc__readCTECycleClause();
	else if (MATCH("COMMONTABLEEXPR", 15))
		fc_return_value = fc__readCommonTableExpr();
	else if (MATCH("MERGEWHENCLAUSE", 15))
		fc_return_value = fc__readMergeWhenClause();
	else if (MATCH("MERGEACTION", 11))
		fc_return_value = fc__readMergeAction();
	else if (MATCH("SETOPERATIONSTMT", 16))
		fc_return_value = fc__readSetOperationStmt();
	else if (MATCH("ALIAS", 5))
		fc_return_value = fc__readAlias();
	else if (MATCH("RANGEVAR", 8))
		fc_return_value = fc__readRangeVar();
	else if (MATCH("INTOCLAUSE", 10))
		fc_return_value = fc__readIntoClause();
	else if (MATCH("TABLEFUNC", 9))
		fc_return_value = fc__readTableFunc();
	else if (MATCH("VAR", 3))
		fc_return_value = fc__readVar();
	else if (MATCH("CONST", 5))
		fc_return_value = fc__readConst();
	else if (MATCH("PARAM", 5))
		fc_return_value = fc__readParam();
	else if (MATCH("AGGREF", 6))
		fc_return_value = fc__readAggref();
	else if (MATCH("GROUPINGFUNC", 12))
		fc_return_value = fc__readGroupingFunc();
	else if (MATCH("WINDOWFUNC", 10))
		fc_return_value = fc__readWindowFunc();
	else if (MATCH("SUBSCRIPTINGREF", 15))
		fc_return_value = fc__readSubscriptingRef();
	else if (MATCH("FUNCEXPR", 8))
		fc_return_value = fc__readFuncExpr();
	else if (MATCH("NAMEDARGEXPR", 12))
		fc_return_value = fc__readNamedArgExpr();
	else if (MATCH("OPEXPR", 6))
		fc_return_value = fc__readOpExpr();
	else if (MATCH("DISTINCTEXPR", 12))
		fc_return_value = fc__readDistinctExpr();
	else if (MATCH("NULLIFEXPR", 10))
		fc_return_value = fc__readNullIfExpr();
	else if (MATCH("SCALARARRAYOPEXPR", 17))
		fc_return_value = fc__readScalarArrayOpExpr();
	else if (MATCH("BOOLEXPR", 8))
		fc_return_value = fc__readBoolExpr();
	else if (MATCH("SUBLINK", 7))
		fc_return_value = fc__readSubLink();
	else if (MATCH("FIELDSELECT", 11))
		fc_return_value = fc__readFieldSelect();
	else if (MATCH("FIELDSTORE", 10))
		fc_return_value = fc__readFieldStore();
	else if (MATCH("RELABELTYPE", 11))
		fc_return_value = fc__readRelabelType();
	else if (MATCH("COERCEVIAIO", 11))
		fc_return_value = fc__readCoerceViaIO();
	else if (MATCH("ARRAYCOERCEEXPR", 15))
		fc_return_value = fc__readArrayCoerceExpr();
	else if (MATCH("CONVERTROWTYPEEXPR", 18))
		fc_return_value = fc__readConvertRowtypeExpr();
	else if (MATCH("COLLATEEXPR", 11))
		fc_return_value = fc__readCollateExpr();
	else if (MATCH("CASEEXPR", 8))
		fc_return_value = fc__readCaseExpr();
	else if (MATCH("CASEWHEN", 8))
		fc_return_value = fc__readCaseWhen();
	else if (MATCH("CASETESTEXPR", 12))
		fc_return_value = fc__readCaseTestExpr();
	else if (MATCH("ARRAYEXPR", 9))
		fc_return_value = fc__readArrayExpr();
	else if (MATCH("ROWEXPR", 7))
		fc_return_value = fc__readRowExpr();
	else if (MATCH("ROWCOMPAREEXPR", 14))
		fc_return_value = fc__readRowCompareExpr();
	else if (MATCH("COALESCEEXPR", 12))
		fc_return_value = fc__readCoalesceExpr();
	else if (MATCH("MINMAXEXPR", 10))
		fc_return_value = fc__readMinMaxExpr();
	else if (MATCH("SQLVALUEFUNCTION", 16))
		fc_return_value = fc__readSQLValueFunction();
	else if (MATCH("XMLEXPR", 7))
		fc_return_value = fc__readXmlExpr();
	else if (MATCH("NULLTEST", 8))
		fc_return_value = fc__readNullTest();
	else if (MATCH("BOOLEANTEST", 11))
		fc_return_value = fc__readBooleanTest();
	else if (MATCH("COERCETODOMAIN", 14))
		fc_return_value = fc__readCoerceToDomain();
	else if (MATCH("COERCETODOMAINVALUE", 19))
		fc_return_value = fc__readCoerceToDomainValue();
	else if (MATCH("SETTODEFAULT", 12))
		fc_return_value = fc__readSetToDefault();
	else if (MATCH("CURRENTOFEXPR", 13))
		fc_return_value = fc__readCurrentOfExpr();
	else if (MATCH("NEXTVALUEEXPR", 13))
		fc_return_value = fc__readNextValueExpr();
	else if (MATCH("INFERENCEELEM", 13))
		fc_return_value = fc__readInferenceElem();
	else if (MATCH("TARGETENTRY", 11))
		fc_return_value = fc__readTargetEntry();
	else if (MATCH("RANGETBLREF", 11))
		fc_return_value = fc__readRangeTblRef();
	else if (MATCH("JOINEXPR", 8))
		fc_return_value = fc__readJoinExpr();
	else if (MATCH("FROMEXPR", 8))
		fc_return_value = fc__readFromExpr();
	else if (MATCH("ONCONFLICTEXPR", 14))
		fc_return_value = fc__readOnConflictExpr();
	else if (MATCH("APPENDRELINFO", 13))
		fc_return_value = fc__readAppendRelInfo();
	else if (MATCH("RANGETBLENTRY", 13))
		fc_return_value = fc__readRangeTblEntry();
	else if (MATCH("RANGETBLFUNCTION", 16))
		fc_return_value = fc__readRangeTblFunction();
	else if (MATCH("TABLESAMPLECLAUSE", 17))
		fc_return_value = fc__readTableSampleClause();
	else if (MATCH("NOTIFYSTMT", 10))
		fc_return_value = fc__readNotifyStmt();
	else if (MATCH("DEFELEM", 7))
		fc_return_value = fc__readDefElem();
	else if (MATCH("DECLARECURSORSTMT", 17))
		fc_return_value = fc__readDeclareCursorStmt();
	else if (MATCH("PLANNEDSTMT", 11))
		fc_return_value = fc__readPlannedStmt();
	else if (MATCH("PLAN", 4))
		fc_return_value = fc__readPlan();
	else if (MATCH("RESULT", 6))
		fc_return_value = fc__readResult();
	else if (MATCH("PROJECTSET", 10))
		fc_return_value = fc__readProjectSet();
	else if (MATCH("MODIFYTABLE", 11))
		fc_return_value = fc__readModifyTable();
	else if (MATCH("APPEND", 6))
		fc_return_value = fc__readAppend();
	else if (MATCH("MERGEAPPEND", 11))
		fc_return_value = fc__readMergeAppend();
	else if (MATCH("RECURSIVEUNION", 14))
		fc_return_value = fc__readRecursiveUnion();
	else if (MATCH("BITMAPAND", 9))
		fc_return_value = fc__readBitmapAnd();
	else if (MATCH("BITMAPOR", 8))
		fc_return_value = fc__readBitmapOr();
	else if (MATCH("SCAN", 4))
		fc_return_value = fc__readScan();
	else if (MATCH("SEQSCAN", 7))
		fc_return_value = fc__readSeqScan();
	else if (MATCH("SAMPLESCAN", 10))
		fc_return_value = fc__readSampleScan();
	else if (MATCH("INDEXSCAN", 9))
		fc_return_value = fc__readIndexScan();
	else if (MATCH("INDEXONLYSCAN", 13))
		fc_return_value = fc__readIndexOnlyScan();
	else if (MATCH("BITMAPINDEXSCAN", 15))
		fc_return_value = fc__readBitmapIndexScan();
	else if (MATCH("BITMAPHEAPSCAN", 14))
		fc_return_value = fc__readBitmapHeapScan();
	else if (MATCH("TIDSCAN", 7))
		fc_return_value = fc__readTidScan();
	else if (MATCH("TIDRANGESCAN", 12))
		fc_return_value = fc__readTidRangeScan();
	else if (MATCH("SUBQUERYSCAN", 12))
		fc_return_value = fc__readSubqueryScan();
	else if (MATCH("FUNCTIONSCAN", 12))
		fc_return_value = fc__readFunctionScan();
	else if (MATCH("VALUESSCAN", 10))
		fc_return_value = fc__readValuesScan();
	else if (MATCH("TABLEFUNCSCAN", 13))
		fc_return_value = fc__readTableFuncScan();
	else if (MATCH("CTESCAN", 7))
		fc_return_value = fc__readCteScan();
	else if (MATCH("NAMEDTUPLESTORESCAN", 19))
		fc_return_value = fc__readNamedTuplestoreScan();
	else if (MATCH("WORKTABLESCAN", 13))
		fc_return_value = fc__readWorkTableScan();
	else if (MATCH("FOREIGNSCAN", 11))
		fc_return_value = fc__readForeignScan();
	else if (MATCH("CUSTOMSCAN", 10))
		fc_return_value = fc__readCustomScan();
	else if (MATCH("JOIN", 4))
		fc_return_value = fc__readJoin();
	else if (MATCH("NESTLOOP", 8))
		fc_return_value = fc__readNestLoop();
	else if (MATCH("MERGEJOIN", 9))
		fc_return_value = fc__readMergeJoin();
	else if (MATCH("HASHJOIN", 8))
		fc_return_value = fc__readHashJoin();
	else if (MATCH("MATERIAL", 8))
		fc_return_value = fc__readMaterial();
	else if (MATCH("MEMOIZE", 7))
		fc_return_value = fc__readMemoize();
	else if (MATCH("SORT", 4))
		fc_return_value = fc__readSort();
	else if (MATCH("INCREMENTALSORT", 15))
		fc_return_value = fc__readIncrementalSort();
	else if (MATCH("GROUP", 5))
		fc_return_value = fc__readGroup();
	else if (MATCH("AGG", 3))
		fc_return_value = fc__readAgg();
	else if (MATCH("WINDOWAGG", 9))
		fc_return_value = fc__readWindowAgg();
	else if (MATCH("UNIQUE", 6))
		fc_return_value = fc__readUnique();
	else if (MATCH("GATHER", 6))
		fc_return_value = fc__readGather();
	else if (MATCH("GATHERMERGE", 11))
		fc_return_value = fc__readGatherMerge();
	else if (MATCH("HASH", 4))
		fc_return_value = fc__readHash();
	else if (MATCH("SETOP", 5))
		fc_return_value = fc__readSetOp();
	else if (MATCH("LOCKROWS", 8))
		fc_return_value = fc__readLockRows();
	else if (MATCH("LIMIT", 5))
		fc_return_value = fc__readLimit();
	else if (MATCH("NESTLOOPPARAM", 13))
		fc_return_value = fc__readNestLoopParam();
	else if (MATCH("PLANROWMARK", 11))
		fc_return_value = fc__readPlanRowMark();
	else if (MATCH("PARTITIONPRUNEINFO", 18))
		fc_return_value = fc__readPartitionPruneInfo();
	else if (MATCH("PARTITIONEDRELPRUNEINFO", 23))
		fc_return_value = fc__readPartitionedRelPruneInfo();
	else if (MATCH("PARTITIONPRUNESTEPOP", 20))
		fc_return_value = fc__readPartitionPruneStepOp();
	else if (MATCH("PARTITIONPRUNESTEPCOMBINE", 25))
		fc_return_value = fc__readPartitionPruneStepCombine();
	else if (MATCH("PLANINVALITEM", 13))
		fc_return_value = fc__readPlanInvalItem();
	else if (MATCH("SUBPLAN", 7))
		fc_return_value = fc__readSubPlan();
	else if (MATCH("ALTERNATIVESUBPLAN", 18))
		fc_return_value = fc__readAlternativeSubPlan();
	else if (MATCH("EXTENSIBLENODE", 14))
		fc_return_value = fc__readExtensibleNode();
	else if (MATCH("PARTITIONBOUNDSPEC", 18))
		fc_return_value = fc__readPartitionBoundSpec();
	else if (MATCH("PARTITIONRANGEDATUM", 19))
		fc_return_value = fc__readPartitionRangeDatum();
	else
	{
		elog(ERROR, "badly formatted node string \"%.32s\"...", fc_token);
		fc_return_value = NULL;	/* 保持编译器安静 */
	}

	return (Node *) fc_return_value;
}


/*
 * readDatum
 *
 * 给定常量的字符串表示，重新创建适当的
 * Datum。字符串表示嵌入了长度信息，但不是 byValue，
 * 所以我们必须被告知这一点。
 */
Datum readDatum(bool fc_typbyval)
{
	Size		fc_length,
				fc_i;
	int			fc_tokenLength;
	const char *fc_token;
	Datum		fc_res;
	char	   *fc_s;

	/*
	 * 读取值的实际长度
	 */
	fc_token = pg_strtok(&fc_tokenLength);
	fc_length = atoui(fc_token);

	fc_token = pg_strtok(&fc_tokenLength);	/* 读取 '[' */
	if (fc_token == NULL || fc_token[0] != '[')
		elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
			 fc_token ? fc_token : "[NULL]", fc_length);

	if (fc_typbyval)
	{
		if (fc_length > (Size) sizeof(Datum))
			elog(ERROR, "byval datum but length = %zu", fc_length);
		fc_res = (Datum) 0;
		fc_s = (char *) (&fc_res);
		for (fc_i = 0; fc_i < (Size) sizeof(Datum); fc_i++)
		{
			fc_token = pg_strtok(&fc_tokenLength);
			fc_s[fc_i] = (char) atoi(fc_token);
		}
	}
	else if (fc_length <= 0)
		fc_res = (Datum) NULL;
	else
	{
		fc_s = (char *) palloc(fc_length);
		for (fc_i = 0; fc_i < fc_length; fc_i++)
		{
			fc_token = pg_strtok(&fc_tokenLength);
			fc_s[fc_i] = (char) atoi(fc_token);
		}
		fc_res = PointerGetDatum(fc_s);
	}

	fc_token = pg_strtok(&fc_tokenLength);	/* 读取 ']' */
	if (fc_token == NULL || fc_token[0] != ']')
		elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
			 fc_token ? fc_token : "[NULL]", fc_length);

	return fc_res;
}

/*
 * readAttrNumberCols
 */
AttrNumber * readAttrNumberCols(int fc_numCols)
{
	int			fc_tokenLength,
				fc_i;
	const char *fc_token;
	AttrNumber *fc_attr_vals;

	if (fc_numCols <= 0)
		return NULL;

	fc_attr_vals = (AttrNumber *) palloc(fc_numCols * sizeof(AttrNumber));
	for (fc_i = 0; fc_i < fc_numCols; fc_i++)
	{
		fc_token = pg_strtok(&fc_tokenLength);
		fc_attr_vals[fc_i] = atoi(fc_token);
	}

	return fc_attr_vals;
}

/*
 * readOidCols
 */
Oid * readOidCols(int fc_numCols)
{
	int			fc_tokenLength,
				fc_i;
	const char *fc_token;
	Oid		   *fc_oid_vals;

	if (fc_numCols <= 0)
		return NULL;

	fc_oid_vals = (Oid *) palloc(fc_numCols * sizeof(Oid));
	for (fc_i = 0; fc_i < fc_numCols; fc_i++)
	{
		fc_token = pg_strtok(&fc_tokenLength);
		fc_oid_vals[fc_i] = atooid(fc_token);
	}

	return fc_oid_vals;
}

/*
 * readIntCols
 */
int *
readIntCols(int fc_numCols)
{
	int			fc_tokenLength,
				fc_i;
	const char *fc_token;
	int		   *fc_int_vals;

	if (fc_numCols <= 0)
		return NULL;

	fc_int_vals = (int *) palloc(fc_numCols * sizeof(int));
	for (fc_i = 0; fc_i < fc_numCols; fc_i++)
	{
		fc_token = pg_strtok(&fc_tokenLength);
		fc_int_vals[fc_i] = atoi(fc_token);
	}

	return fc_int_vals;
}

/*
 * readBoolCols
 */
bool *
readBoolCols(int fc_numCols)
{
	int			fc_tokenLength,
				fc_i;
	const char *fc_token;
	bool	   *fc_bool_vals;

	if (fc_numCols <= 0)
		return NULL;

	fc_bool_vals = (bool *) palloc(fc_numCols * sizeof(bool));
	for (fc_i = 0; fc_i < fc_numCols; fc_i++)
	{
		fc_token = pg_strtok(&fc_tokenLength);
		fc_bool_vals[fc_i] = strtobool(fc_token);
	}

	return fc_bool_vals;
}
